﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using BareWeb.HtmlExtension.Extensions;
using Fiddler;


namespace BareWeb.HtmlExtension
{
    public sealed partial class HtmlInspectorControl : UserControl
    {
        public List<string> Filenames { get; set; }
        public string CurrFile { get; set; }

        public HtmlInspectorControl(bool showSplitContainer) :this()
        {
            if (!showSplitContainer)
            {
                splitContainer1.Panel1Collapsed = true;
            }
        }

        public HtmlInspectorControl()
        {
            InitializeComponent();

            this.AllowDrop = true;
            base.DragEnter += HtmlInspectorControl_DragEnter;
            base.DragDrop += HtmlInspectorControl_DragDrop;
            base.DragLeave += HtmlInspectorControl_DragLeave;

            Filenames = new List<string>();
        }

        void HtmlInspectorControl_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent("Fiddler.Session[]"))
            {
                e.Effect = DragDropEffects.Copy;
                this.BackColor = Color.LightBlue;
                label3.BackColor = Color.FromKnownColor(KnownColor.Turquoise);
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        void HtmlInspectorControl_DragLeave(object sender, EventArgs e)
        {
            this.BackColor = Color.FromKnownColor(KnownColor.Control);
            label3.BackColor = Color.FromKnownColor(KnownColor.Info);
        }

        void HtmlInspectorControl_DragDrop(object sender, DragEventArgs e)
        {
            this.BackColor = Color.FromKnownColor(KnownColor.Control);
            label3.BackColor = Color.FromKnownColor(KnownColor.Info);
            Session[] data = (Session[])e.Data.GetData("Fiddler.Session[]");
            if ((data != null) && (data.Length >= 1))
            {
                var validator = new HtmlInfoHelper();
                for (int i = 0; i < data.Length; i++)
                {
                    if (validator.IsValid(data[i]))
                    {
                        Session oSession = data[i];

                        DoInspect(oSession);
                    }
                    else
                    {
                            DoLog("{0} did not have a content-type of HTML or had a zero size", data[i].url);
                    }

                    e.Effect = DragDropEffects.None;
                }
            }
        }

         public void DoInspect(Session oSession)
        {
            DoInspect(oSession.fullUrl, oSession.GetResponseBodyAsString());
        }

        public void DoInspect(string title, string body)
        {
            try
            {
                chtRequest.Visible = true;
                pbHistory.Visible = false;

                DoLog("Inspecting: {0}", title);
           
                double sum = 0D;
                chtRequest.Series.Clear();
                chtRequest.Series.Add(new Series("Data Makeup"));
                chtRequest.Series[0].ChartType = SeriesChartType.Pie;
                chtRequest.Titles.Clear();
                chtRequest.Series[0]["PieLabelStyle"] = "Outside";
                chtRequest.Series[0]["PieDrawingStyle"] = "SoftEdge";
                chtRequest.Series[0].BorderWidth = 1;
                chtRequest.Series[0].BorderColor = System.Drawing.Color.FromArgb(26, 59, 105);

                // Set the pie chart to be 3D
                chtRequest.ChartAreas[0].Area3DStyle.Enable3D = true;
                // 0degree inclination flattens the image to look 2D but preserves non-overlapping labels
                chtRequest.ChartAreas[0].Area3DStyle.Inclination = 0;

                chtRequest.Legends.Clear();
                chtRequest.Legends.Add("Legend1");
                chtRequest.Legends[0].Enabled = true;
                chtRequest.Legends[0].Docking = Docking.Bottom;
                chtRequest.Legends[0].Alignment = System.Drawing.StringAlignment.Center;
                chtRequest.Series[0].LegendText = "#PERCENT{P1}";

                chtRequest.Titles.Add(new Title(title, Docking.Top));

                var info = new HtmlInfoHelper().DoInspection(body);


                DataPoint dpViewState = new DataPoint()
                                            {
                                                AxisLabel = "ViewState",
                                                YValues =
                                                    new[]
                                                        {
                                                            info.ViewStateSize
                                                        }
                                            };
                chtRequest.Series[0].Points.Add(dpViewState);


                DataPoint dpForm = new DataPoint()
                                       {
                                           AxisLabel = "Form Elements",
                                           YValues = new []
                                                         {
                                                             info.FormElementsSize
                                                         }
                                       };
                chtRequest.Series[0].Points.Add(dpForm);

                DataPoint dpLongIds = new DataPoint()
                                          {
                                              AxisLabel = "LongIdentifiers",
                                              YValues = new []
                                                            {
                                                                info.LongIdentifierSize
                                                            }
                                          };
                chtRequest.Series[0].Points.Add(dpLongIds);



                DataPoint dpCommentNodes = new DataPoint()
                                               {
                                                   AxisLabel = "HTML Comments",
                                                   YValues = new []
                                                                 {
                                                                     info.CommentsSize
                                                                 }
                                               };
                chtRequest.Series[0].Points.Add(dpCommentNodes);


                DataPoint dpScriptImports = new DataPoint()
                                                {
                                                    AxisLabel = "Script Imports",
                                                    YValues = new []
                                                                  {
                                                                      info.ScriptImportsSize
                                                                  }
                                                };
                chtRequest.Series[0].Points.Add(dpScriptImports);



                DataPoint dpHead = new DataPoint()
                                       {
                                           AxisLabel = "<head>",
                                           YValues = new [] {info.HeadSize}
                                       };
                chtRequest.Series[0].Points.Add(dpHead);


                DataPoint dpWhitespace = new DataPoint()
                                             {
                                                 AxisLabel = "Whitespace",
                                                 YValues = new [] {info.WhitespaceSize}
                                             };
                chtRequest.Series[0].Points.Add(dpWhitespace);

                DataPoint dpBody = new DataPoint()
                                       {
                                           AxisLabel = "Content",
                                           YValues = new [] {info.RemainingBodySize}
                                       };
                chtRequest.Series[0].Points.Add(dpBody);

                //sort the data into a useful order
                chtRequest.DataManipulator.Sort(PointSortOrder.Descending, chtRequest.Series[0]);
                chtRequest.Show();

                string tmpFile = System.IO.Path.GetTempFileName();
                chtRequest.SaveImage(tmpFile, ChartImageFormat.Png);
                Filenames.Add(tmpFile);
                CurrFile = tmpFile;

                DoNextPrevVisibility();
            }
            catch (Exception ex)
            {
                FiddlerApplication.ReportException(ex, "Exception in Inspection");
            }
        }

        private void DoNextPrevVisibility()
        {
            if (Filenames == null || !Filenames.Any())
            {
                btnPrev.Enabled = false;
                btnNext.Enabled = false;
            }
            else if (Filenames.IndexOf(CurrFile) == Filenames.Count() - 1)
            {
                if (Filenames.Count() > 1)
                    btnPrev.Enabled = true;

                btnNext.Enabled = false;
            }
            else if (Filenames.IndexOf(CurrFile) == 0)
            {
                btnPrev.Enabled = false;

                if (Filenames.Count() > 1)
                {
                    btnNext.Enabled = true;
                }
            }
            else
            {
                btnPrev.Enabled = true;
                btnNext.Enabled = true;
            }
        }

        private void DoLog(string format, params object[] args)
        {
            FiddlerApplication.Log.LogString(string.Format(format, args));
        }        

        private void DotNetGeneratorControl_Load(object sender, EventArgs e)
        {
        }

        private void chtRequest_Click(object sender, EventArgs e)
        {
            var result = saveFileDialog1.ShowDialog(this);
            if (result == DialogResult.OK)
            {
                chtRequest.SaveImage(saveFileDialog1.FileName, ChartImageFormat.Png);
            }
        }

        private void btnPrev_Click(object sender, EventArgs e)
        {
            int idx = Filenames.IndexOf(CurrFile);
            CurrFile = Filenames[idx - 1];

            chtRequest.Visible = false;
            pbHistory.Visible = true;
            pbHistory.Load(CurrFile);            

            DoNextPrevVisibility();
        }

        private void bntNext_Click(object sender, EventArgs e)
        {
            int idx = Filenames.IndexOf(CurrFile);
            CurrFile = Filenames[idx + 1];

            chtRequest.Visible = false;
            pbHistory.Visible = true;
            pbHistory.Load(CurrFile);   

            DoNextPrevVisibility();
        }

    }
}
